using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

using Zsa.Emulation.PPU;
using System.IO;

namespace Zsa.Emulation.Render.Video.Gdi
{
    /// <summary>
    /// Graphics render that uses direct draw.
    /// </summary>
    public class GdiGraphicRender : GraphicRender
    {
        #region Fields

        /// <summary>
        /// The current frame.
        /// </summary>
        private Bitmap _NameTableImage;

        /// <summary>
        /// The current frame.
        /// </summary>
        private Bitmap _FrameBuffer;

        /// <summary>
        /// The screen graphics object.
        /// </summary>
        private Graphics _ScreenGraphics;

        /// <summary>
        /// A backbuffer graphics object.
        /// </summary>
        private Graphics _BackBufferGraphics;

        /// <summary>
        /// The device pixel format.
        /// </summary>
        private PixelFormat _PixelFormat = PixelFormat.Format32bppArgb;

        #endregion Fields

        #region Constructor
        /// <summary>
        /// Initializes a new instance of the <see cref="T:D3dGraphicRender"/> class.
        /// </summary>
        public GdiGraphicRender(GdiRenderSettings settings)
            : base ( settings )
        {

        }
        #endregion Constructor

        #region Methods

        /// <summary>
        /// Draws the frame on to the screen.
        /// </summary>
        public override void DrawScreen()
        {
            //DebugSaveBackground();
            GraphicsUnit _Unit = GraphicsUnit.Pixel;

            // Lock the name table bitmap image.
            BitmapData _BitmapData =
                _NameTableImage.LockBits(
                    new Rectangle(0, 0, _NameTableImage.Width, _NameTableImage.Height),
                    ImageLockMode.WriteOnly,
                    _PixelFormat
                );

            

            // Write the name table.  NEED TO CHANGE TO ALLOW 24 BIT
            base.WriteTable(_BitmapData.Scan0, _BitmapData.Stride, 4);

            DrawSprites(_BitmapData.Scan0, _BitmapData.Stride, 4);
            // Unlock the bits.
            _NameTableImage.UnlockBits(_BitmapData);

            // Copy the bitmap?  why i dont know.....  
            // converts to 24 bit.  need to add support in write table for 24 bit.
            MemoryStream _Stream = new MemoryStream();
            _NameTableImage.Save(_Stream, ImageFormat.Bmp);
            _NameTableImage = Bitmap.FromStream(_Stream) as Bitmap;
            _NameTableImage.MakeTransparent(Color.Pink);
            
            // Fill the ppu color
            _BackBufferGraphics.FillRectangle(
                new SolidBrush(Ppu.BackgroundColor), RenderArea);

            // Draw the nametable image to the backbuffer.
            _BackBufferGraphics.DrawImage(_NameTableImage, 0, 0,
                SurfaceControl.Width, SurfaceControl.Height);
            
            // Flip on to the screen.
            _ScreenGraphics.DrawImage(_FrameBuffer, new Point(0, 0));
        }

        /// <summary>
        /// Creates or recreates the device.
        /// </summary>
        protected override void OnRecreateDevice()
        {
            Dispose(_NameTableImage, _FrameBuffer, _BackBufferGraphics, _ScreenGraphics);

            _NameTableImage = new Bitmap(256, 256, _PixelFormat);
            _FrameBuffer = new Bitmap(Width, Height, _PixelFormat);

            _ScreenGraphics = Graphics.FromHwnd(base.SurfaceControl.Handle);
            _BackBufferGraphics = Graphics.FromImage(_FrameBuffer);

        }

        /// <summary>
        /// Initialize the graphic render.
        /// </summary>
        /// <param name="renderSettings"></param>
        protected override void OnUpdateRenderSettings(GraphicRenderSettings renderSettings)
        {
            
        }

        /// <summary>
        /// Disposes the specified objects.
        /// </summary>
        /// <param name="args">The args.</param>
        private void Dispose(params IDisposable[] args)
        {
            for (int _TempIndex = 0; _TempIndex < args.Length; _TempIndex++)
            {
                try
                {
                    if (args[_TempIndex] != null)
                    {
                        args[_TempIndex].Dispose();
                    }
                }
                catch (ObjectDisposedException) 
                {
                    Console.WriteLine("Ignored the disposed");
                }
                catch (Exception excep )
                { 
                    
                }
            }
        }

        /// <summary>
        /// Called when [dispose].
        /// </summary>
        protected override void OnDispose()
        {
            Dispose(_NameTableImage, _FrameBuffer, _BackBufferGraphics, _ScreenGraphics);
        }

        #region Event Handlers
        /// <summary>
        /// Handles the Resize event of the SurfaceControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        void SurfaceControl_Resize(object sender, EventArgs e)
        {

        }
        #endregion Event Handlers


        #endregion Methods







        #region Properties

       
        #endregion Properties




    }


}
